#include "memmap.h"
#include <stdio.h>
#include "dumpregsCfg"
#include "hexdump.h"
#include <stdlib.h>
#include <string.h>

#define BSPMD_DISPLAY_BYTE_WIDTH    16
#define BSPMD_FILE_LINE_MAXLEN      2048
#define BSPMD_REGDUMP_FILE          "/var/custom/pdcConfig/regdump.txt"
#define BSPMD_REGDUMP_NEW_FILE      "/var/custom/pdcConfig/regdump_new.txt"

static int bspmd_l(FILE *stream, unsigned long startAddr, unsigned long endAddr)
{
	unsigned long ul_addr = 0;
	void *p_mem  = NULL;
	unsigned long len;

    ul_addr = startAddr;
	len = endAddr - startAddr + 1;

	p_mem = memmap(ul_addr, len);
	if (p_mem == NULL)
    {
		printf("[0x%lx,0x%lx] Memory Map error\n", startAddr, endAddr);
        return -1;
    }
    if (stream)
    {
        bsp_hexdump(stream, p_mem, startAddr, len, BSPMD_DISPLAY_BYTE_WIDTH);
    }
    else
    {
	    bsp_hexdump(stdout, p_mem, startAddr, len, BSPMD_DISPLAY_BYTE_WIDTH);
    }
	
    memunmap(p_mem);

	return 0;
}

int dumpregs(int argc, char *argv[])
{
    FILE * fd;
    FILE * fdNew;
    (void)argc;
    (void)argv;
    char        *lineBuf    =   NULL;
    char        *lineBufNew =   NULL;
    unsigned long startAddr;
    unsigned long endAddr;
    int           lineCount = 0;
    int           lineLen   = 0;

    //打开文件
    fd = fopen(BSPMD_REGDUMP_FILE,"r");
    if (NULL == fd)
    {
        printf("open %s fail\n", BSPMD_REGDUMP_FILE);
        return -1;
    }
    fdNew = fopen(BSPMD_REGDUMP_NEW_FILE,"w");
    if (NULL == fd)
    {
        fclose(fd);
        printf("open %s fail\n", BSPMD_REGDUMP_NEW_FILE);
        return -1;
    }
    //找到寄存器范围
    lineBuf=(char*)malloc(sizeof(char) * (BSPMD_FILE_LINE_MAXLEN + 1));
    memset(lineBuf, 0, BSPMD_FILE_LINE_MAXLEN + 1);
    while(fgets(lineBuf, BSPMD_FILE_LINE_MAXLEN, fd) != NULL)
    {
        if(strncmp(lineBuf,"[reg range:",11))
        {
            goto go_continue;
        }
        sscanf(lineBuf, "[reg range:%lx-%lx]", &startAddr, &endAddr);
        if (startAddr > endAddr)
        {
            printf("warn : startAddr[0x%lx] > endAddr[0x%lx]\n", startAddr, endAddr);
            goto go_continue;
        }

        //读寄存器值,并保存
        fputs(lineBuf, fdNew);
        if (bspmd_l(fdNew, startAddr, endAddr))
        {
            fclose(fd);
            fclose(fdNew);
            return -1;
        }
go_continue:
        memset(lineBuf, 0, BSPMD_FILE_LINE_MAXLEN + 1);
    }
    fclose(fd);
    fputs("\n", fdNew);
    fclose(fdNew);
    
    //比较差异，并显示差异
    fd = fopen(BSPMD_REGDUMP_FILE,"r");
    if (NULL == fd)
    {
        printf("open %s fail\n", BSPMD_REGDUMP_FILE);
        return -1;
    }
    fdNew = fopen(BSPMD_REGDUMP_NEW_FILE,"r");
    if (NULL == fd)
    {
        fclose(fd);
        printf("open %s fail\n", BSPMD_REGDUMP_NEW_FILE);
        return -1;
    }
    lineBufNew=(char*)malloc(sizeof(char) * (BSPMD_FILE_LINE_MAXLEN + 1));
    memset(lineBuf, 0, BSPMD_FILE_LINE_MAXLEN + 1);
    memset(lineBufNew, 0, BSPMD_FILE_LINE_MAXLEN + 1);
    while((fgets(lineBuf, BSPMD_FILE_LINE_MAXLEN, fd))&&(fgets(lineBufNew, BSPMD_FILE_LINE_MAXLEN, fdNew)))
    {
        lineCount++;
        lineLen = strlen(lineBufNew)-1;  //取到结尾回车
        if (0 != strncmp(lineBuf, lineBufNew, lineLen))
        {
            printf("regdump.txt <--diff-->regdump_new.txt\n");
            lineBuf[lineLen]=0;
            lineBufNew[lineLen]=0;
            printf("%d:%s\n", lineCount, lineBuf);
            printf("%d:%s\n", lineCount, lineBufNew);
        }
        memset(lineBuf, 0, BSPMD_FILE_LINE_MAXLEN + 1);
        memset(lineBufNew, 0, BSPMD_FILE_LINE_MAXLEN + 1);
    }

    fclose(fd);
    fclose(fdNew);
    free(lineBuf);
    free(lineBufNew);
    
    return 0;
}